package cn.szsys.integration.helper.business.impl;

import cn.szsys.integration.billrule.BillingMapperUtils;
import cn.szsys.integration.billrule.annoation.BillRule;
import cn.szsys.integration.billrule.entity.BillingInfo;
import cn.szsys.integration.constants.BillRuleRecordTypeEnum;
import cn.szsys.integration.constants.EconomicCapabilityConstant;
import cn.szsys.integration.constants.ZxyrResultMapperedEnum;
import cn.szsys.integration.dto.EconomicCapabilityDTO;
import cn.szsys.integration.ex.BusinessException;
import cn.szsys.integration.ex.enums.ExceptionEnum;
import cn.szsys.integration.helper.BusinessBeanNameConstant;
import cn.szsys.integration.helper.business.AbstractEconomicCapabilityHandlerChain;
import cn.szsys.integration.util.OkHttpUtil;
import cn.szsys.integration.util.R;
import cn.szsys.integration.util.RSAUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * zhongxingyinrong
 *
 * @author Ryan
 * @since 2025-05-12
 **/
@Component(BusinessBeanNameConstant.EconomicCapability.ZXYR_ECONOMIC_CAPABILITY_HANDLER_CHAIN)
@Slf4j
public class ZxyrEconomicCapabilityHandlerChain extends AbstractEconomicCapabilityHandlerChain {
    private static final Map<String, String> CODE_MAP = new HashMap<>();

    static {
        CODE_MAP.put(EconomicCapabilityConstant.CODE_FIN_CAPACITY_00, "financial_2w_013");
        CODE_MAP.put(EconomicCapabilityConstant.CODE_FIN_CAPACITY_01, "financial_10w_v8_014");
        CODE_MAP.put(EconomicCapabilityConstant.CODE_FIN_CAPACITY_02, "financial_10w_v9_015");
    }

    @Value("${economic-capability.yr.url}")
    private String url;
    @Value("${economic-capability.yr.app-id}")
    private String appId;
    @Value("${economic-capability.yr.private-key}")
    private String privateKey;
    @Value("${economic-capability.yr.public-key}")
    private String publicKey;


    /**
     * 转换对应结果并设置计费信息
     *
     * @param obj           obj
     * @param consumingTime consumingTime
     * @return {@link R}
     * @author Ryan
     */
    @Override
    public R<?> convertResultAndBilling(JSONObject obj, long consumingTime) {
        //{"status":"200","msg":"成功","num":"c223e130-0671-4caa-a572-50b85fd0965b","timestamp":"1747186957526","data":"mpHGGveDxsjY27vDnzH+O1krbVLwKnyyAMtJZOUFNu1SJaQhc9sZwItdbZvm1WRGJ6aZq+U/yKa8a1mkIFY/zg4ALk+ZZ/ivuqloEfa39zPzzkxTBu8saFPmOi3HuzV9fbOEIgVp5Xv2RnWDKcDP+KPfrPji2MsEmHeKjf3np0iPOQvsRoWrR0ju6YeK7DWsCjz32hcM2ZKQhzBXCfGqZd/IxJBAY3HC9EhgbxwONmoSM9zJ8G+aPZQEd21ueZGU2sKdRG8WM2U+1HSVLbjxda+i0mzCPGBSBKYdhCC7G7oXZt2XI2qyru9daCYp2Hr19hvfYMepwTar5lLKE7VmQQ=="}
        if (Objects.equals("200", obj.getString("status"))) {
            String resultData = obj.getString("data");
            //解密后json数据。
            String decrypt;
            try {
                decrypt = RSAUtil.decrypt(resultData, privateKey);
            } catch (Exception e) {
                log.error("解密消息体失败,error msg: {}", e.getMessage(), e);
                return R.error(ExceptionEnum.SYS_ERR);
            }
            log.info("针对YR响应data解密, data decrypt: {}", decrypt);
            //设置计费数据
            JSONObject dataObj = JSON.parseObject(decrypt);
            String code = dataObj.getString("code");
            ZxyrResultMapperedEnum byUpstreamCode = ZxyrResultMapperedEnum.getByUpstreamCode(code);
            BillingInfo billingInfo = BillingInfo.build(byUpstreamCode.getDownstreamCode(), code, consumingTime);
            BillingMapperUtils.set(billingInfo);
            return R.success(dataObj);
        }
        ZxyrResultMapperedEnum byUpstreamCode = ZxyrResultMapperedEnum.NONE;
        BillingInfo billingInfo = BillingInfo.build(byUpstreamCode.getDownstreamCode(), byUpstreamCode.getUpstreamCode(), consumingTime);
        BillingMapperUtils.set(billingInfo);
        return R.error(ExceptionEnum.OP_FAIL);
    }

    /**
     * 执行业务处理
     *
     * @param dto          参数
     * @param reqStartTime reqStartTime
     * @return {@link R}
     * @author Ryan
     */
    @Override
    public R<?> doHandle(EconomicCapabilityDTO dto, long reqStartTime) {
        ZxyrEconomicCapabilityHandlerChain thisChain = (ZxyrEconomicCapabilityHandlerChain) AopContext.currentProxy();
        return switch (dto.getCode()) {
            case EconomicCapabilityConstant.CODE_FIN_CAPACITY_00 -> thisChain.productOne(dto, reqStartTime);
            case EconomicCapabilityConstant.CODE_FIN_CAPACITY_01 -> thisChain.productTwo(dto, reqStartTime);
            case EconomicCapabilityConstant.CODE_FIN_CAPACITY_02 -> thisChain.productThree(dto, reqStartTime);
            default -> R.error(ExceptionEnum.OP_FAIL);
        };
    }

    @BillRule(upstream = "zhongxingyinrong", billRuleRecordType = BillRuleRecordTypeEnum.DAY, product = "经济能力2W")
    public R<?> productOne(EconomicCapabilityDTO dto, long reqStartTime) {
        return request(dto, reqStartTime);
    }

    @BillRule(upstream = "zhongxingyinrong", billRuleRecordType = BillRuleRecordTypeEnum.DAY, product = "经济能力10W_v8")
    public R<?> productTwo(EconomicCapabilityDTO dto, long reqStartTime) {
        return request(dto, reqStartTime);
    }

    @BillRule(upstream = "zhongxingyinrong", billRuleRecordType = BillRuleRecordTypeEnum.DAY, product = "经济能力10W_v9")
    public R<?> productThree(EconomicCapabilityDTO dto, long reqStartTime) {
        return request(dto, reqStartTime);
    }

    /**
     * 发送请求
     *
     * @param dto          dto
     * @param reqStartTime reqStartTime
     * @return {@link R<?>}
     * @author Ryan
     */
    public R<?> request(EconomicCapabilityDTO dto, long reqStartTime) {
        JSONObject businessData = new JSONObject();
        businessData.put("idCard", dto.getIdCard());
        businessData.put("name", dto.getName());
        businessData.put("mobile", dto.getMobile());

        String jsonData = businessData.toJSONString();
        String encrypt;
        String sign;
        try {
            encrypt = RSAUtil.encrypt(jsonData, publicKey);
            sign = RSAUtil.sign(jsonData, privateKey);
        } catch (Exception e) {
            log.error("参数加密/加签异常,error msg: {}", e.getMessage(), e);
            return R.error(ExceptionEnum.SYS_ERR);
        }
        long startTime = System.currentTimeMillis();
        JSONObject reqJson = new JSONObject();
        reqJson.put("appId", appId);
        reqJson.put("code", CODE_MAP.get(dto.getCode()));
        reqJson.put("timestamp", startTime);
        reqJson.put("auth", sign);
        reqJson.put("data", encrypt);

        String bodyRaw = JSON.toJSONString(reqJson);
        log.info("请求YR查询经济能力[请求], body :{}", bodyRaw);
        OkHttpUtil.OkhttpResponse response = OkHttpUtil.builder()
                .url(url)
                .post(bodyRaw)
                .sync();

        long endTime = System.currentTimeMillis();
        log.info("请求YR查询经济能力[响应], response: {}, 请求耗时: {}ms", response.getData(), (endTime - startTime));

        if (response.getSuccess()) {
            JSONObject obj = JSON.parseObject(response.getData());
            return convertResultAndBilling(obj, reqStartTime - startTime);
        }
        throw new BusinessException(ExceptionEnum.OP_FAIL, "请求出错!");
    }
}
